<script setup lang="tsx">
import { computed, ref } from 'vue'
import { getPermissionsApi, updatePermissionApi, deletePermissionApi } from '@/api/permission'
import type { PermissionItemType, UpdatePermissionPayloadType } from '@/types/api/permission'
import { NTree, NDropdown, useMessage } from 'naive-ui'
import type { TreeOption, DropdownOption } from 'naive-ui'
import { FolderOutline } from '@vicons/ionicons5'
import { renderIcon } from '@/utils/common'
import SaveModal from './SaveModal/index.vue'

const message = useMessage()

// 查询权限列表
const permissions = ref<PermissionItemType[]>([])
const getPermissions = async () => {
  const result = await getPermissionsApi({})
  permissions.value = result.content
}
getPermissions()

// treeData
const treeData = computed(() => {
  return traversePermission(permissions.value)
})
// 递归遍历权限，返回treeData
const traversePermission = (permissions: PermissionItemType[]): TreeOption[] => {
  return permissions.map((permission) => {
    const { id, permissionName, children, type, path } = permission
    return {
      label: permissionName,
      key: id,
      children: children.length ? traversePermission(children) : undefined,
      prefix: type === 'menu' && !path ? renderIcon(FolderOutline) : undefined
    }
  })
}
// save弹窗ref
const saveModalRef = ref<InstanceType<typeof SaveModal> | null>(null)
const openSaveModal = () => {
  saveModalRef.value && (saveModalRef.value.showModal = true)
}
// 点击右键时鼠标位置
const mousePosition = ref({
  x: 0,
  y: 0
})
// 右键菜单是否可见
const dropdownVisible = ref(false)
// 右键菜单下拉选项
const dropdownOptions = ref<DropdownOption[]>([])
// 右键时所在的权限id
const currentPermissionId = ref('')
// 右键时所在的权限
const currentPermission = computed(() => {
  // 新增操作时为null
  return dropdownSelectKey.value === 'create'
    ? null
    : findPermissionById(permissions.value, currentPermissionId.value)
})
const findPermissionById = (
  permissions: PermissionItemType[],
  id: string
): PermissionItemType | null => {
  for (const permission of permissions) {
    if (permission.id === id) {
      return permission
    }
    if (permission.children.length) {
      const ret = findPermissionById(permission.children, id)
      if (ret) return ret
    }
  }
  return null
}
// 为节点增加事件
const nodeProps = ({ option }: { option: TreeOption }) => ({
  // 右键
  oncontextmenu: (e: MouseEvent): void => {
    const { prefix, key } = option
    currentPermissionId.value = key as string
    mousePosition.value.x = e.clientX
    mousePosition.value.y = e.clientY
    e.preventDefault()
    e.stopPropagation()
    if (prefix) {
      dropdownOptions.value = [
        {
          label: '新增权限',
          key: 'create'
        },
        {
          label: '编辑权限',
          key: 'update'
        },
        {
          label: '删除权限',
          key: 'delete'
        }
      ]
    } else {
      // 没有prefix为button权限，不能新增权限
      dropdownOptions.value = [
        {
          label: '编辑权限',
          key: 'update'
        },
        {
          label: '删除权限',
          key: 'delete'
        }
      ]
    }
    dropdownVisible.value = true
  }
})
// 处理右键菜单选择
const dropdownSelectKey = ref('')
const handleDropdownSelect = (key: string | number, option: DropdownOption) => {
  dropdownSelectKey.value = key.toString()
  switch (key) {
    case 'create':
      openSaveModal()
      break
    case 'update':
      openSaveModal()
      break
    case 'delete':
      deletePermission()
      break
    default:
      console.warn('nothing to du')
  }
  dropdownVisible.value = false
}

// 删除权限
const deletePermission = async () => {
  await deletePermissionApi(currentPermissionId.value)
  message.success('删除成功')
  actionCallback()
}

// 操作后回调
const actionCallback = () => {
  getPermissions()
}

// 处理拖拽释放
const handleDrop = async (data: {
  node: TreeOption
  dragNode: TreeOption
  dropPosition: 'before' | 'inside' | 'after'
  event: DragEvent
}) => {
  const { node, dragNode } = data
  const targetId = node.key as string
  const id = dragNode.key as string
  const targetPermission = findPermissionById(permissions.value, targetId)
  if (targetPermission?.type === 'button') {
    return message.error('不能拖放到按钮权限中')
  }
  const permission = findPermissionById(permissions.value, id) as PermissionItemType
  const payload: UpdatePermissionPayloadType = {
    ...permission,
    parentId: targetId
  }
  await updatePermissionApi(payload)
  message.success('更新成功')
  actionCallback()
}

const handleOutsideRightClick = (e: MouseEvent) => {
  currentPermissionId.value = '0'
  mousePosition.value.x = e.clientX
  mousePosition.value.y = e.clientY
  dropdownOptions.value = [
    {
      label: '新增权限',
      key: 'create'
    }
  ]
  dropdownVisible.value = true
}
</script>

<template>
  <div class="permission-container" @contextmenu.prevent="handleOutsideRightClick">
    <NTree
      :data="treeData"
      :default-expand-all="true"
      :block-line="true"
      :draggable="true"
      :node-props="nodeProps"
      @drop="handleDrop"
    />
    <!-- 右键菜单 -->
    <NDropdown
      trigger="manual"
      placement="bottom-start"
      :show="dropdownVisible"
      :x="mousePosition.x"
      :y="mousePosition.y"
      :options="dropdownOptions"
      @contextmenu.prevent
      @clickoutside="() => (dropdownVisible = false)"
      @select="handleDropdownSelect"
    />
    <!-- 保存权限弹窗 -->
    <SaveModal
      ref="saveModalRef"
      :id="currentPermissionId"
      :record="currentPermission"
      :onOk="actionCallback"
    />
  </div>
</template>

<style lang="scss" scoped>
.permission-container {
  height: 100vh;
  overflow: auto;
}
</style>
